import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
import { useMainContentContext } from "@/service/general/publicStatic";
import { message, Popover, Steps } from "antd";
import { CloseSvg, DeleteSvg, EyeSvg, FileV1Svg, InputSvg, LinkV1Svg, PrePageSvg, SettingSvg, SvgQuest, TextDatasetSvg, TextSegmentationSvt, UploadV1Svg } from "@/app/assets/CustomizeSvg";
import { CreateDatasetType, PreType, TrainingType, UploadStatus } from "@/service/general/enumType";
import { UtilHelpers } from "@/service/general/utils/utilHelpers";
import { StatusConfig } from "@/service/general/modal/common";
import { KnowledgeBaseModal } from "@/service/request/modal/dataModal";
import { createFileDataset, createLinkDataset, createTextDataset } from "@/service/request/requestApi";
import { FileInfo, LinkInfo, RequestTextModal } from "@/service/request/modal/requestModal";
import { ResponsePageModal } from "@/service/request/modal/responseModal";
import { fileTypes } from "@/service/general/fileMIME";
import uuid from "react-uuid";

import "./addtextdataset.css"

interface StepsView {
    title: string,
    topText: string,
    preType: PreType,
    content: (...args: any[]) => ReactNode,
}

interface DataItem {
    id: string,
    name: string,
    upStatus: StatusConfig,
}

enum preType {
    preText,
    preSegmentation
}

const StepsViews: StepsView[] = [{
    title: "选择文件",
    topText: "退出",
    preType: PreType.returnPage,
    content: ({param, type, setParam, callback}: {param: RequestTextModal, type: CreateDatasetType, setParam: (param: RequestTextModal) => void ,callback?: (param?: any) => void}) => (<InputData param={param} type={type} setParam={setParam} callback={callback} />),
},{
    title: "数据处理",
    topText: "上一步",
    preType: PreType.preSteps,
    content: ({param, type, setParam, callback}: {param: RequestTextModal, type: CreateDatasetType, setParam: (param: RequestTextModal) => void ,callback?: (param?: any) => void}) => (<ProcessingData param={param} type={type} setParam={setParam} callback={callback} />),
},{
    title: "确认上传",
    topText: "上一步",
    preType: PreType.preSteps,
    content: ({param, type, setParam, callback}: {param: RequestTextModal, type: CreateDatasetType, setParam: (param: RequestTextModal) => void ,callback?: (param?: any) => void}) => (<SubmitUp param={param} type={type} setParam={setParam} callback={callback} />),
}];

const STATUS_CONFIGS: Record<UploadStatus, StatusConfig> = {
    [UploadStatus.Wait]: {
        status: UploadStatus.Wait,
        bgColor: "bg-gray-300",
        text: "等待中",
    },
    [UploadStatus.Loading]: {
        status: UploadStatus.Loading,
        bgColor: "bg-blue-300 animate-pulse animate-[pulse_2s_cubic-bezier(0.4,0,0.6,1)_1]",
        text: "创建中",
    },
    [UploadStatus.Success]: {
        status: UploadStatus.Success,
        bgColor: "bg-green-300 animate-pulse animate-[pulse_2s_cubic-bezier(0.4,0,0.6,1)_1]",
        text: "成功",
    },
    [UploadStatus.Error]: {
        status: UploadStatus.Error,
        bgColor: "bg-red-300 animate-pulse animate-[pulse_2s_cubic-bezier(0.4,0,0.6,1)_1]",
        text: "失败",
    },
}

const AddTextDataset = ({
    data, 
    type, 
    callback
}: {
    data: KnowledgeBaseModal, 
    type?: CreateDatasetType,
    callback?: (param?: any) => void
}) => {
    const {goBack} = useMainContentContext();
    const [current,setCurrent] = useState<number>(0);
    const [stepItem, setStepItem] = useState<StepsView>(StepsViews[current]);
    const [requestParam, setRequestParam] = useState<RequestTextModal>({
        id: data.id,
        name: "",
        text: "",
        selector: "",
        trainingType: TrainingType.CHUNK,
        link: [],
        files: []
    });

    const StepsItems = StepsViews.map((item, index) => ({key: index, title: item.title}));
    useEffect(() => {
        Initialize();
    });

    const Initialize = () => {
        if (!data) {
            goBack();
        }
    }

    const Dispose = () => {
    }

    const preStep = () => {
        console.log("param: \n", requestParam);
        if (stepItem.preType === PreType.returnPage) {
            goBack();
            return;
        }
        changStep(-1);
    }

    const nextStep = () => {
        changStep(1);
    }

    const changStep = (index: number) => {
        const stepIndex = current + index;
        setCurrent(stepIndex);
        setStepItem(StepsViews[stepIndex]);
    }

    const getContent = () => {
        let callback = nextStep;
        if (current === (StepsViews.length - 1)) callback = goBack;
        return stepItem.content({param: requestParam, type: type, setParam: setRequestParam, callback: callback});
    }

    return (<>
        <div className="w-full h-full p-1 text-black">
            <div className="w-full h-full rounded-xl bg-white py-4 px-8 flex flex-col items-start justify-start gap-4">
                <div className="flex flex-row items-center justify-start gap-1 text-gray-800">
                    <div className="rotate-180 w-7 h-7 flex flex-row items-center justify-center hover:text-blue-600 cursor-pointer" onClick={preStep}><PrePageSvg width={`100%`} height={`100%`} /></div>
                    <div className="text-base">{stepItem.topText}</div>
                </div>
                <div className="w-full px-80 py-4 bg-gray-100 border border-gray-200 shadow-inherit rounded-lg text-black">
                    <Steps current={current} items={StepsItems}></Steps>
                </div>
                <div className="w-full flex-1 min-h-0 flex flex-col items-start justify-start">
                    {getContent()}
                </div>
            </div>
        </div>
    </>);
}

const InputData = ({param, type, setParam, callback}: {param: RequestTextModal, type: CreateDatasetType, setParam: (param: RequestTextModal) => void ,callback?: (param?: any) => void}) => {
    const getView = () => {
        switch(type) {
            case CreateDatasetType.TEXT: 
                return <TextData param={param} setParam={setParam} callback={callback} />;
            case CreateDatasetType.URLLINK: 
                return <UrlLinkData param={param} setParam={setParam} callback={callback} />;
            case CreateDatasetType.FILE:
                return <FileData param={param} setParam={setParam} callback={callback} />;
            default: 
                return <TextData param={param} setParam={setParam} callback={callback} />;
        }
    }
    return (
        <>
            {getView()}
        </>
    );
}

const TextData = ({param, setParam, callback}: {param: RequestTextModal, setParam: (param: RequestTextModal) => void ,callback?: (param?: any) => void}) => {
    const nameInput = useRef<HTMLInputElement>(null);
    const textTextArea = useRef<HTMLTextAreaElement>(null);
    const handleValueChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
        const {name, value} = e.currentTarget || e.target;
        if (isValidKey(name)) {
            setParam({
                ...param,
                [name]: value
            });
        }
    };

    const isValidKey = (key: string): key is keyof RequestTextModal => {
        return Object.keys(param).includes(key);
    }

    const nextStep = () => {
        if (!param.name || param.name.length <= 0) {
            nameInput.current?.focus();
            return;
        }
        if (!param.text || param.text.length <= 0) {
            textTextArea.current?.focus();
            return;
        }
        if (callback) {
            callback();
        }
    }

    return (<>
        <div className="input-textarea w-full flex flex-col items-start justify-start gap-5 overflow-y-auto">
            <div className="flex flex-row items-center justify-center gap-12">
                <div>数据集名称</div>
                <div 
                className="flex flex-row items-center justify-center w-80 h-9 py-2 px-4 rounded-lg border bg-gray-100 border-gray-200 shadow-[0_0_5px_rgb(96,165,250,0.1)] shadow-transparent hover:border-blue-400 has-[input:focus-within]:border-blue-400 has-[input:focus-within]:shadow-blue-400">
                    <input type="text" ref={nameInput} name="name" value={param.name} placeholder="数据集名称" onChange={handleValueChange} className="border-none outline-none w-full h-full bg-transparent" />
                </div>
            </div>
            <div className="flex flex-row items-start justify-center gap-12">
                <div>数据集内容</div>
                <div 
                className="flex flex-row items-center justify-center w-[500px] h-80 py-2 px-4 rounded-lg border bg-gray-100 border-gray-200 shadow-[0_0_5px_rgb(96,165,250,0.1)] shadow-transparent hover:border-blue-400 has-[textarea:focus-within]:border-blue-400 has-[textarea:focus-within]:shadow-blue-400">
                    <textarea ref={textTextArea} name="text" value={param.text} placeholder="数据集内容" onChange={handleValueChange} className="input-textarea border-none outline-none w-full h-full bg-transparent resize-none"></textarea>
                </div>
            </div>
            <div className="w-full h-fit flex flex-row items-center justify-end">
                <div className="cursor-pointer px-5 py-2 rounded-lg bg-blue-500 text-white hover:bg-blue-500/80" onClick={nextStep}>下一步</div>
            </div>
        </div>
    </>);
}

const UrlLinkData = ({param, setParam, callback}: {param: RequestTextModal, setParam: (param: RequestTextModal) => void ,callback?: (param?: any) => void}) => {
    const selectorInput = useRef<HTMLInputElement>(null);
    const linkTextArea = useRef<HTMLTextAreaElement>(null);
    const [warnTextArea, setWarnTextArea] = useState<boolean>(false);

    const handleValueChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
        const {name, value} = e.currentTarget || e.target;

        let _value: string | LinkInfo[];
        if (name === "link") {
            const tmpValue: LinkInfo[] = [];
            value.split('\n').map(item => {
                const linkItem: LinkInfo = {
                    id: uuid(),
                    url: item
                }
                tmpValue.push(linkItem);
            });
            if (tmpValue.length > 10) {
                setWarnTextArea(true);
                message.warning("超过允许最大输入10行");
                setTimeout(() => setWarnTextArea(false), 200);
                return;
            }
            _value = [...tmpValue];
        } else {
            _value = value;
        }
        if (isValidKey(name)) {
            setParam({
                ...param,
                [name]: _value
            });
        }
    };

    const isValidKey = (key: string): key is keyof RequestTextModal => {
        return Object.keys(param).includes(key);
    }

    const getLinkList = () => {
        return param.link.filter(item => item.url !== "");
    }

    const removeLink = (key: string ,removeId: string) => {
        if (isValidKey(key)) {
            const _value = param.link.filter(item => item.id !== removeId);
            setParam({
                ...param,
                [key]: _value
            })
        }
    }

    const nextStep = () => {
        // if (!param.name || param.name.length <= 0) {
        //     selectorInput.current?.focus();
        //     return;
        // }
        if (!param.link || param.link.length <= 0) {
            linkTextArea.current?.focus();
            return;
        }
        if (callback) {
            callback();
        }
    }

    return (
        <>
            <div className="input-textarea w-1/2 flex flex-col items-start justify-start gap-5 overflow-y-auto py-3">
                <div className="w-full flex flex-row items-start justify-between px-1">
                    <div className="w-28">网络链接</div>
                    <div 
                    style={warnTextArea ? {
                        borderColor: "#dc2626",
                        boxShadow: "0 0 5px rgba(220, 38, 38, 1)"
                    }:{}}
                    className="flex flex-row items-center justify-center w-[750px] h-56 py-2 px-4 rounded-lg border bg-gray-100 border-gray-200 shadow-[0_0_5px_rgba(96,165,250,0.1)] shadow-transparent hover:border-blue-400 has-[textarea:focus-within]:border-blue-400 has-[textarea:focus-within]:shadow-blue-400">
                        <textarea rows={10} ref={linkTextArea} name="link" value={param.link.map(item => item.url).join('\n')} placeholder="仅支持静态链接，如果上传后数据为空，可能该链接无法被读取。每行一个，每次最多 10 个链接" onChange={handleValueChange} className="input-textarea border-none outline-none w-full h-full bg-transparent resize-none"></textarea>
                    </div>
                </div>
                <div className="w-full flex flex-row items-start justify-between">
                    <div className="w-28 flex flex-col items-start justify-center">
                        <div>选择器</div>
                        <div 
                        className="decoration-gray-500 text-gray-500 cursor-pointer hover:underline"
                        onClick={() => {window.open('https://doc.tryfastgpt.ai/docs/guide/knowledge_base/websync/#%E9%80%89%E6%8B%A9%E5%99%A8%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8', '_blank', 'noopener,noreferrer')}}>使用教程</div>
                    </div>
                    <div className="w-[750px] flex flex-row items-center justify-start">
                        <div 
                        className="flex flex-row items-center justify-center w-80 h-9 py-2 px-4 rounded-lg border bg-gray-100 border-gray-200 shadow-[0_0_5px_rgb(96,165,250,0.1)] shadow-transparent hover:border-blue-400 has-[input:focus-within]:border-blue-400 has-[input:focus-within]:shadow-blue-400">
                            <input type="text" ref={selectorInput} name="selector" value={param.selector} placeholder="body .content #document" onChange={handleValueChange} className="border-none outline-none w-full h-full bg-transparent" />
                        </div>
                    </div>
                </div>
                <div className="w-full flex flex-row items-start justify-between">
                    <div className="w-28"></div>
                    <div className="w-[750px] flex flex-row items-center justify-start gap-3 flex-wrap">
                        {
                            getLinkList().map((item, index) => (
                                <>
                                <div key={`link_view_${item.id}_${index}`} className="max-w-full flex flex-row items-center justify-center gap-5 px-3 py-2 border border-transparent bg-gray-100 rounded-md cursor-pointer hover:border-blue-500">
                                    <div className="max-w-full flex-1 flex flex-row items-center justify-center gap-2">
                                        <div className="w-5 flex flex-row items-center justify-center text-blue-500 p-[2px]"><LinkV1Svg width={`100%`} height={`100%`} /></div>
                                        <div className="flex-1 break-all">{item.url}</div>
                                    </div>
                                    <div 
                                    className="w-5 p-[2px] rounded-full text-black cursor-pointer flex flex-row items-center justify-center hover:bg-gray-200"
                                    onClick={() => {removeLink("link", item.id)}}
                                    >
                                        <CloseSvg width={`100%`} height={`100%`} />
                                    </div>
                                </div>
                                </>
                            ))
                        }
                        
                    </div>
                </div>
                <div className="w-full h-fit flex flex-row items-center justify-end">
                    <div className="cursor-pointer px-5 py-2 rounded-lg bg-blue-500 text-white hover:bg-blue-500/80" onClick={nextStep}>下一步</div>
                </div>
            </div>
        </>
    );
}

const FileData = ({param, setParam, callback}: {param: RequestTextModal, setParam: (param: RequestTextModal) => void ,callback?: (param?: any) => void}) => {
    const fileInput = useRef<HTMLInputElement>(null);
    const [upLoadTip, setUpLoadTip] = useState<string>("点击或拖动文件到此处上传");
    const AcceptValue = [...Object.keys(fileTypes).map(item => `.${item.toLowerCase()}`), ...Object.values(fileTypes)].join(',');

    const handleClick = () => {
        fileInput.current?.click();
    }

    const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const files = e.target.files || [];
        handleFile(Array.from(files));
    }

    const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
        e.preventDefault();
        setUpLoadTip("松开鼠标上传文件");
    }

    const handleDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
        e.preventDefault();
        setUpLoadTip("点击或拖动文件到此处上传");
    }

    const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
        e.preventDefault();
        setUpLoadTip("点击或拖动文件到此处上传");
        const files = e.dataTransfer.files;
        handleFile(Array.from(files));
    }

    const handleFile = (files: File[] | null) => {
        let fileInfos: FileInfo[] = [...param.files];
        files?.map((item, index) => {
            const fileData: FileInfo = {
                id: uuid(),
                fileName: item.name,
                fileSize: item.size,
                upProgress: 0,
                data: item,
                fileId: ''
            }
            fileInfos.push({...fileData});
        });
        changeParam({key: "files", value: fileInfos});
    }

    const removeFile = (removeId: string | number) => {
        console.log("files: \n", param.files);
        const fileInfos: FileInfo[] = param.files.filter((item) => item.id !== removeId);
        changeParam({key: "files", value: fileInfos});
    }

    const changeParam = ({key, value}:{key: string, value: any}) => {
        if (isValidKey(key)) {
            setParam({
                ...param,
                [key]: value
            });
        }
    }

    const isValidKey = (key: string): key is keyof RequestTextModal => {
        return Object.keys(param).includes(key);
    }

    const nextStep = () => {
        if (param.files.length <= 0) return;
        // if (!param.name || param.name.length <= 0) {
        //     selectorInput.current?.focus();
        //     return;
        // }
        // if (!param.link || param.link.length <= 0) {
        //     linkTextArea.current?.focus();
        //     return;
        // }
        if (callback) {
            callback();
        }
    }
    return (
        <>
            <div className="input-textarea w-full flex flex-col items-start justify-start gap-5 overflow-y-auto py-3">
                <div 
                className="w-full flex flex-col items-center justify-center gap-2 border border-gray-400 border-dashed rounded-lg py-6 cursor-pointer hover:border-blue-600 hover:bg-blue-50" 
                onClick={handleClick}
                onDragOver={handleDragOver}
                onDragLeave={handleDragLeave}
                onDrop={handleDrop}
                >
                    <div className="w-full flex flex-row items-center justify-center">
                        <div className="w-8 flex flex-row items-center justify-center text-blue-500"><UploadV1Svg width={`100%`} height={`100%`} /></div>
                    </div>
                    <div className="w-full flex flex-row items-center justify-center text-lg font-bold">
                        {upLoadTip}
                    </div>
                    <div className="w-full flex flex-col items-center justify-center text-sm text-gray-600">
                        <div>支持 .txt, .docx, .csv, .xlsx, .pdf, .md, .html, .pptx 类型文件</div>
                        <div>最多支持 1000 个文件，单个文件最大 500 MB</div>
                    </div>
                </div>
                <div className="w-full flex flex-col items-center justify-center">
                    {
                        param.files && param.files.length > 0 ? (
                            <>
                                <div className="w-full flex flex-row items-center justify-center bg-gray-100 rounded-xl px-7 py-4 font-bold">
                                    <div className="flex-[5] flex flex-row items-center justify-start">文件名</div>
                                    <div className="flex-[2] flex flex-row items-center justify-start">文件大小</div>
                                    <div className="flex-[2] flex flex-row items-center justify-start">操作</div>
                                </div>
                                <div className="w-full flex flex-col items-center justify-center">
                                    {
                                        param.files.map((item, index) => (
                                            <>
                                            <div key={`file_row_${item.id}_${index}`} className="w-full flex flex-row items-center justify-center px-7 py-4 border-b border-b-gray-300 border-dashed cursor-pointer hover:bg-gray-200">
                                                <div className="flex-[5] flex flex-row items-center justify-start gap-2">
                                                    <div className="w-5 text-sky-500 flex flex-row items-center justify-center"><FileV1Svg width={`100%`} height={`100%`} /></div>
                                                    <div>{item.fileName}</div>
                                                </div>
                                                <div className="flex-[2] flex flex-row items-center justify-start">{UtilHelpers.formatFileSize(Number(item.fileSize || '0'), 2)}</div>
                                                <div className="flex-[2] flex flex-row items-center justify-start">
                                                    <div className="w-fit p-1 rounded-sm hover:bg-gray-200" onClick={() => removeFile(item.id)}>
                                                        <div className="w-4 flex flex-row items-center justify-center text-red-500/70 hover:text-red-600">
                                                            <DeleteSvg width={`100%`} height={`100%`} />
                                                        </div>
                                                    </div>
                                                </div>
                                            </div>
                                            </>
                                        ))
                                    }
                                </div>
                            </>
                        ):(<></>)
                    }
                </div>
                <div className="w-full h-fit flex flex-row items-center justify-end">
                    <div className={`px-5 py-2 rounded-lg ${param.files.length > 0 ? "bg-blue-500 cursor-pointer": "bg-blue-500/80 cursor-not-allowed select-none"} text-white hover:bg-blue-500/80`} onClick={nextStep}>下一步</div>
                </div>
            </div>
            <input type="file" ref={fileInput} className="hidden" multiple accept={AcceptValue} onChange={handleFileInputChange} />
        </>
    );
}

const ProcessingData = ({param, type, setParam, callback}: {param: RequestTextModal, type: CreateDatasetType, setParam: (param: RequestTextModal) => void ,callback?: (param?: any) => void}) => {
    const directRadio = useRef<HTMLInputElement>(null);
    const qaRadio = useRef<HTMLInputElement>(null);
    const [preview, setPreview] = useState<boolean>(false);
    const [previewType, setPreviewType] = useState<preType>(preType.preText);
    const [previewData, setPreviewData] = useState<string | string[]>([]); 
    const sectionLength = 700;
    const sectionSize = 15;

    
    useEffect(() => {
        if (directRadio.current && qaRadio.current) {
            directRadio.current.defaultChecked = directRadio.current.value === param.trainingType;
            qaRadio.current.defaultChecked = qaRadio.current.value === param.trainingType;
        }
    });

    const selectHandleType = (radio: HTMLInputElement | null) => {
        if (!radio) return;
        radio.checked = true;
        changeParam({key: "trainingType",value: radio.value});
    }

    const changeParam = ({key, value}:{key: string, value: any}) => {
        if (isValidKey(key)) {
            setParam({
                ...param,
                [key]: value
            });
        }
    }

    const isValidKey = (key: string): key is keyof RequestTextModal => {
        return Object.keys(param).includes(key);
    }

    const getSourceList = (): string[] => {
        if (type === CreateDatasetType.TEXT) {
            return [param.name];
        }
        if (type === CreateDatasetType.URLLINK) {
            return param.link.map(item => item.url);
        }
        if (type === CreateDatasetType.FILE) {
            return param.files.map((item) => item.fileName);
        }
        return [];
    }

    const handlePreview = (pretype: preType) => {
        if (type === CreateDatasetType.TEXT) {
            setPreviewType(pretype);
            setPreview(true);
            if (pretype === preType.preText) {
                setPreviewData(param.text.slice(0, 3000));
            } else if (pretype === preType.preSegmentation) {
                setPreviewData(UtilHelpers.textSplitter({text: param.text, chunksLength: sectionLength, chunksSize: sectionSize}));
            }
        }
        if (type === CreateDatasetType.URLLINK) {
            // TODO:
        }
        if (type === CreateDatasetType.FILE) {

        }
        
    }

    const nextStep = () => {
        if (callback) {
            callback();
        }
    }
    
    return (<>
        <div className="w-full h-full flex flex-row items-start justify-start gap-6">
            <div className="flex flex-col items-start justify-center gap-4">
                <div className="flex flex-row items-center justify-start text-lg">
                    <div className="flex flex-row items-center justify-center w-7"><SettingSvg width={`100%`} height={`100%`} /></div>
                    <div>数据处理</div>
                </div>
                <div className="flex flex-row items-center justify-start gap-6">
                    <div className="text-nowrap">处理方式</div>
                    <div className="flex flex-row items-center justify-start gap-4">
                        <div className="flex flex-row items-center justify-between w-fit gap-3 rounded-lg border border-gray-200 px-3 py-2 cursor-pointer shadow-[0_0_5px_rgb(96,165,250,0.1)] shadow-transparent hover:border-blue-400 has-[:checked]:border-blue-400 has-[:checked]:shadow-blue-400" onClick={() => selectHandleType(directRadio.current)}>
                            <div className="flex flex-row items-center justify-start gap-4">
                                <div className="flex flex-row items-center justify-center">
                                    <input type="radio" ref={directRadio} value={TrainingType.CHUNK} defaultChecked={param.trainingType === TrainingType.CHUNK} name="handle_type" id="direct_segmentation" />
                                </div>
                                <div>直接分段</div>
                            </div>
                            <Popover content={<>
                                <div className="max-w-72">
                                    将文本按照一定规则进行分段处理后，转成可进行语义搜索的格式，适合绝大多数场景。不需要调用模型额外处理，成本低。
                                </div>
                                </>} trigger="hover" placement="bottom">
                            <div className="flex flex-row items-center justify-center"><SvgQuest /></div>
                            </Popover>
                        </div>
                        <div className="flex flex-row items-center justify-between w-fit gap-3 rounded-lg border border-gray-200 px-3 py-2 cursor-pointer  shadow-[0_0_5px_rgb(96,165,250,0.1)] shadow-transparent hover:border-blue-400 has-[:checked]:border-blue-400 has-[:checked]:shadow-blue-400" onClick={() => selectHandleType(qaRadio.current)}>
                            <div className="flex flex-row items-center justify-start gap-4">
                                <div className="flex flex-row items-center justify-center">
                                    <input type="radio" ref={qaRadio} value={TrainingType.QA} defaultChecked={param.trainingType === TrainingType.QA} name="handle_type" id="qa_segmentation" />
                                </div>
                                <div>问答分段</div>
                            </div>
                            <Popover content={<>
                                <div className="max-w-72">
                                    根据一定规则，将文本拆成一段较大的段落，调用AI为该段落生成问答对。有非常高的检索精度，但是会丢失很多内容细节。
                                </div>
                                </>} trigger="hover" placement="bottom">
                                <div className="flex flex-row items-center justify-center"><SvgQuest /></div>
                            </Popover>
                        </div>
                    </div>
                </div>
                <div className="flex flex-row items-start justify-center gap-6">
                    <div className="text-nowrap">处理参数</div>
                    <div className="flex flex-row items-start justify-start w-[500px] gap-4 rounded-lg border border-gray-200 px-3 py-3 cursor-pointer  shadow-[0_0_5px_rgb(96,165,250,0.1)] shadow-transparent hover:border-blue-400 has-[:checked]:border-blue-400 has-[:checked]:shadow-blue-400">
                        <div className="flex flex-row items-center justify-center py-1"><input type="radio" defaultChecked={true} name="handle_param" id="auto_param" /></div>
                        <div className="flex flex-col items-start justify-center">
                            <div>自动</div>
                            <div className="text-gray-500">自动设置分割和预处理规则</div>
                        </div>
                    </div>
                </div>
                <div className="w-full h-fit flex flex-row items-center justify-end">
                    <div className="cursor-pointer px-5 py-2 rounded-lg bg-blue-500 text-white hover:bg-blue-500/80" onClick={nextStep}>下一步</div>
                </div>
            </div>
            <div className="w-full h-full flex flex-col items-start justify-center gap-4">
                <div className="flex flex-row items-center justify-center text-lg gap-1">
                    <div className="flex flex-row items-center justify-center w-4"><TextDatasetSvg width={`100%`} height={`100%`} /></div>
                    <div>来源列表</div>
                </div>
                <div className="input-textarea flex-1 min-h-0 flex flex-row items-start justify-center flex-wrap py-3 overflow-y-auto">
                    <div className="w-full h-fit flex flex-row items-stretch justify-start flex-wrap gap-3">
                    {
                        getSourceList().map((item, index) => (
                            <div key={`preview_${index}`} className="flex flex-row items-center justify-center gap-2 px-6 py-4 border border-gray-300 rounded-lg shadow shadow-gray-200">
                                <div className="flex flex-row items-center justify-start gap-1">
                                    <div className="text-blue-500 flex flex-row items-center justify-center"><InputSvg /></div>
                                    <div className="w-[450px] text-wrap break-words">{item}</div>
                                </div>
                                <div className="flex flex-row items-center justify-center">
                                    {
                                        type === CreateDatasetType.TEXT ? (
                                            <>
                                                <Popover content={
                                                    <>
                                                        <div className="flex flex-col items-center justify-center p-3 gap-1">
                                                            <div 
                                                            className="w-full flex flex-row items-center justify-start gap-2 px-3 py-2 rounded-md hover:bg-gray-100 cursor-pointer"
                                                            onClick={() => {handlePreview(preType.preText)}}
                                                            >
                                                                <div className="flex flex-row items-center justify-center w-4"><TextDatasetSvg /></div>
                                                                <div>预览源文本（最多3000字）</div>
                                                            </div>
                                                            <div 
                                                            className="w-full flex flex-row items-center justify-start gap-2 px-3 py-2 rounded-md hover:bg-gray-100 cursor-pointer"
                                                            onClick={() => {handlePreview(preType.preSegmentation)}}
                                                            >
                                                                <div className="flex flex-row items-center justify-center w-4"><TextSegmentationSvt /></div>
                                                                <div>预览分段（最多15段）</div>
                                                            </div>
                                                        </div>
                                                    </>
                                                } arrow={false} trigger="hover" placement="bottomLeft" overlayInnerStyle={{padding: 0, margin: 0}}>
                                                    <div className="px-2 py-[6px] rounded-md border border-gray-300 shadow-[0_0_5px_rgb(96,165,250,0.1)] shadow-gray-300 cursor-pointer hover:bg-gray-200 hover:text-blue-500 hover:border-blue-500 hover:shadow-blue-400 flex flex-row items-center justify-center">
                                                        <EyeSvg />
                                                    </div>
                                                </Popover>
                                            </>
                                        ):(<></>)
                                    }
                                </div>
                            </div>
                        ))}
                    </div>
                </div>
            </div>
        </div>
        <div 
        className="fixed w-screen h-screen top-0 left-0 bg-black/20"
        style={{
            display: preview ? "block" : "none"
        }}
        onClick={() => setPreview(false)}
        >
            <div className="w-full h-full bg-transparent flex flex-col items-end justify-center pr-3 py-10">
            {
                previewType === preType.preText ? (
                    <>
                    <div 
                    className="preview-model w-1/4 h-full bg-white my-auto rounded-lg"
                    onClick={(event) => {event.stopPropagation()}}
                    >
                        <div className="flex flex-row items-center justify-between bg-gray-100 py-2 px-5 rounded-ss-lg rounded-se-lg">
                            <div className="flex flex-row items-center justify-start gap-2">
                                <div className="text-blue-500"><InputSvg /></div>
                                <div className="font-bold">{param.name}</div>
                            </div>
                            <div className="w-8 h-8 p-1 transition-all duration-300 text-gray-600 hover:rotate-90 hover:bg-gray-300 rounded-lg cursor-pointer" onClick={() => {setPreview(false)}}>
                                <CloseSvg width={`100%`} height={`100%`} />
                            </div>
                        </div>
                        <div className="py-2 px-5 h-fit whitespace-pre-line break-words">
                            {previewData}
                        </div>
                    </div>
                    </>
                ):(<>
                    <div 
                    className="preview-model w-2/5 h-full bg-white my-auto rounded-lg"
                    onClick={(event) => {event.stopPropagation()}}
                    >
                        <div className="flex flex-row items-center justify-between bg-gray-100 py-2 px-5 rounded-ss-lg rounded-se-lg">
                            <div className="flex flex-row items-center justify-start gap-2">
                                <div className="text-blue-500"><InputSvg /></div>
                                <div className="font-bold">{param.name}</div>
                            </div>
                            <div className="w-8 h-8 p-1 transition-all duration-300 text-gray-600 hover:rotate-90 hover:bg-gray-300 rounded-lg" onClick={() => {setPreview(false)}}>
                                <CloseSvg width={`100%`} height={`100%`} />
                            </div>
                        </div>
                        <div className="py-2 px-5 flex flex-col items-center justify-center gap-3">
                            {
                                previewData && previewData.length > 0 && Array.isArray(previewData) ? previewData.map((item,index) => {
                                    return (<>
                                    <div key={`pre_row_${index}`} className="w-full rounded-lg border border-gray-200 shadow-md shadow-gray-200 py-4 px-4 whitespace-pre-line break-words">{item}</div>
                                    </>);
                                }):(<></>)
                            }
                        </div>
                    </div>
                </>)
            }
            </div>
        </div>
    </>);
}

const SubmitUp = ({param, type, setParam, callback}: {param: RequestTextModal, type: CreateDatasetType, setParam: (param: RequestTextModal) => void ,callback?: (param?: any) => void}) => {
    const [datasets, setDataSets] = useState<DataItem[]>([]);
    const [initData, setInitData] = useState<boolean>(false);
    const [isSubmit, setIsSubmit] = useState<boolean>(false);
    useEffect(() => {
        if (!initData) {
            Initialize();
        }
    });

    const Initialize = () => {
        setInitData(true);
        getDatas();
        // setUpStatus(STATUS_CONFIGS[UploadStatus.Wait]);
        // if (param.name && param.name.length > 0) {
        //     setDataSets([param]);
        // }
    }

    const getDatas = () => {
        if (type === CreateDatasetType.TEXT) {
            const dataItem: DataItem = {
                id: param.id,
                name: param.name,
                upStatus: STATUS_CONFIGS[UploadStatus.Wait]
            }
            setDataSets([{...dataItem}]);
        }
        if (type === CreateDatasetType.URLLINK) {
            const datas: DataItem[] = [];
            param.link.map((item, index) => {
                const dataItem: DataItem = {
                    id: item.id,
                    name: item.url,
                    upStatus: STATUS_CONFIGS[UploadStatus.Wait]
                }
                datas.push({...dataItem});
            });
            setDataSets([...datas]);
        }
        if (type === CreateDatasetType.FILE) {
            const datas: DataItem[] = [];
            param.files.map((item, index) => {
                const dataItem: DataItem = {
                    id: item.id,
                    name: item.fileName,
                    upStatus: STATUS_CONFIGS[UploadStatus.Wait]
                }
                datas.push({...dataItem});
            });
            setDataSets([...datas]);
        }
    }

    const deleteParam = (rmId: string) => {
        if (isSubmit) return;
        setDataSets(datasets.filter((item) => item.id !== rmId));
        if (type === CreateDatasetType.TEXT) {
            removeText(rmId);
        }
        if (type === CreateDatasetType.URLLINK) {
            removeLink(rmId);
        }
        if (type === CreateDatasetType.FILE) {
            removeFile(rmId);
        }
    }

    const removeText = (rmId: string) => {
        setParam({
            id: param.id,
            name: "",
            text: "",
            selector: "",
            trainingType: TrainingType.CHUNK,
            link: [],
            files: []
        });
    }

    const removeLink = (rmId: string) => {
        const link = param.link.filter(item => item.id !== rmId);
        changeParam({key: "link", value: link});
    }

    const removeFile = (rmId: string) => {
        const files = param.files.filter(item => item.id !== rmId);
        changeParam({key: "files", value: files});
    }
    
    const changeDatasets = ({id, key, value}: {id?: string, key: string, value: any}) => {
        setDataSets(items => items.map(item => {
            if (isValidKey(item, key)) {
                if (!id || item.id === id) {
                    return {
                        ...item,
                        [key]: value
                    };
                }
            }
            return {...item};
        }));
    }

    const changeParam = ({key, value}:{key: string, value: any}) => {
        if (isValidKey(param, key)) {
            setParam({
                ...param,
                [key]: value
            });
        }
    }

    const isValidKey = <T extends Object>(obj: T, key: string | number | symbol): key is keyof T => {
        return Object.prototype.hasOwnProperty.call(obj, key);
    }

    const submit = () => {
        // if (datasets.length > 0) {

        // }
        if (isSubmit) return;
        setIsSubmit(true);
        changeDatasets({key: "upStatus", value: STATUS_CONFIGS[UploadStatus.Loading]});
        if (type === CreateDatasetType.TEXT) {
            submitText();
        }
        if (type === CreateDatasetType.URLLINK) {
            submitLink();
        }
        if (type === CreateDatasetType.FILE) {
            submitFile();
        }
    }

    const processItem = useCallback(({id, param, funSubmit}: {id: string, param: any, funSubmit: (param: any) => Promise<any>}) => {
        return new Promise((resolve) => {
            if (funSubmit) {
                funSubmit(param).then((res) => {
                    console.log("res: \n", res);
                    if (res.code === 200 && res.success && res.result) {
                        changeDatasets({id: id, key: "upStatus", value: STATUS_CONFIGS[UploadStatus.Success]});
                        resolve(true);
                    } else {
                        if (res.message && res.message.length > 0) {
                            message.error(res.message);
                        }
                        changeDatasets({id: id, key: "upStatus", value: STATUS_CONFIGS[UploadStatus.Error]});
                        resolve(false);
                    } 
                }).catch((err) => {
                    console.log("操作失败： \n", err);
                    changeDatasets({id: id, key: "upStatus", value: STATUS_CONFIGS[UploadStatus.Error]});
                    resolve(false);
                })
            } else {
                resolve(false);
            }
        });
    }, []);

    const submitText = () => {
        if (param.name && param.name.length > 0) {
            createTextDataset({datasetId: param.id, name: param.name, trainingType: param.trainingType, text: param.text}).then((res: ResponsePageModal<boolean>) => {
                console.log("create text res: \n", res);
                if (res.code === 200 && res.success && res.result) {
                    changeDatasets({id: param.id, key: "upStatus", value: STATUS_CONFIGS[UploadStatus.Success]});
                    if (callback) {
                        callback();
                    }
                } else if (res.message && res.message.length > 0) {
                    message.error(res.message);
                    changeDatasets({id: param.id, key: "upStatus", value: STATUS_CONFIGS[UploadStatus.Error]});
                    return;
                }
            }).catch((err) => {
                changeDatasets({id: param.id, key: "upStatus", value: STATUS_CONFIGS[UploadStatus.Error]});
                console.log("创建失败", err);
                return;
            });
        }
    }

    const submitLink = useCallback(async () => {
        const requests = param.link.map(item => {
            const par = {
                datasetId: param.id,
                trainingType: param.trainingType,
                link: item.url
            }
            return processItem({id: item.id, param: par, funSubmit: createLinkDataset});
        });

        const results = await Promise.all(requests);

        const finalResult = results.every(success => success);

        if (finalResult && callback) {
            callback();
        } 
        setIsSubmit(false);
    }, [param, processItem, callback]);

    const submitFile = useCallback(async () => {
        const requests = param.files.map(item => {
            const par = {
                datasetId: param.id,
                trainingType: param.trainingType,
                file: item.data
            }
            return processItem({id: item.id, param: par, funSubmit: createFileDataset});
        });

        const results = await Promise.all(requests);

        const finalResult = results.every(success => success);

        if (finalResult && callback) {
            callback();
        }
        setIsSubmit(false);
    }, [param, processItem, callback]);

    return (<>
        <div className="w-full flex flex-col items-center justify-center gap-3">
            <div key={`table_up_row`} className="flex flex-row items-center justify-center w-full px-6 py-4 bg-gray-200 rounded-lg">
                <div className="flex-1">来源名</div>
                <div className="flex-1">状态</div>
                <div className="flex-1">操作</div>
            </div>
            <div className="w-full">
                {
                    datasets.map((item, index) => {
                        return (<>
                            <div key={`up_${item.id}_${index}`} className="flex flex-row items-center justify-center w-full px-6 py-4 border-b border-b-gray-100">
                                <div className="flex-1 flex flex-row items-center justify-start gap-2">
                                    <div className="text-blue-400"><InputSvg /></div>
                                    <div>{item.name}</div>
                                </div>
                                <div className="flex-1">
                                    <div className={`${item.upStatus.bgColor} w-fit px-3 py-1 rounded-md cursor-pointer`}>{item.upStatus.text}</div>
                                </div>
                                <div className="flex-1">
                                    <div 
                                    className={`w-7 h-7 bg-gray-200 rounded-md p-2 ${isSubmit ? "bg-gray-200/80 cursor-not-allowed select-none": "hover:bg-red-300/20 hover:text-red-600 cursor-pointer"}`}
                                    onClick={() => {deleteParam(item.id)}}
                                    >
                                        <DeleteSvg width={`100%`} height={`100%`} />
                                    </div>
                                </div>
                            </div>
                        </>);
                    })
                }
            </div>
            <div className="w-full flex flex-row items-center justify-end">
                <div 
                className={`px-3 py-2 rounded-lg text-white ${isSubmit ? "bg-blue-500/80 cursor-not-allowed select-none": "cursor-pointer bg-blue-500 hover:bg-blue-500/90"}`}
                onClick={submit}
                >
                    {`${datasets.length > 0 ? `共${datasets.length}个文件 | ` : ""}开始上传`}
                </div>
            </div>
        </div>
    </>);
}

export {
    AddTextDataset
}